package com.jiaozi.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.jiaozi.base.enums.sys.YesOrNoEnum;
import com.jiaozi.base.redis.RedisEnum;
import com.jiaozi.base.redis.RedisUtil;
import com.jiaozi.core.security.utils.SecurityUtil;
import com.jiaozi.base.utils.bean.R;
import com.jiaozi.system.entity.SysDepartment;
import com.jiaozi.system.entity.SysUserOrRole;
import com.jiaozi.system.enums.ConfigsEnum;
import com.jiaozi.system.mapper.SysUserMapper;
import com.jiaozi.system.entity.SysUser;
import com.jiaozi.system.pojo.param.sys.user.UserPageParam;
import com.jiaozi.system.pojo.param.sys.user.UserPasswordParam;
import com.jiaozi.system.pojo.param.sys.user.UserSaveParam;
import com.jiaozi.system.pojo.param.sys.user.UserUpdateParam;
import com.jiaozi.system.pojo.vo.sys.user.UserInfoVO;
import com.jiaozi.system.pojo.vo.sys.user.UserPageVO;
import com.jiaozi.system.service.SysConfigsService;
import com.jiaozi.system.service.SysDepartmentService;
import com.jiaozi.system.service.SysUserOrRoleService;
import com.jiaozi.system.service.SysUserService;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Function;

/**
 * 系统-用户(SysUser)表服务实现类
 *
 * @author jiaozi
 * @since 2024-08-15 14:02:36
 */
@Service("sysUserService")
@Slf4j
public class SysUserServiceImpl extends MPJBaseServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Autowired
    private SysDepartmentService sysDepartmentService;
    @Autowired
    private SysConfigsService sysConfigsService;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private SysUserOrRoleService sysUserOrRoleService;
    @Override
    public R<IPage<UserPageVO>> userPage(Long pageNum, Long pageSize, UserPageParam param) {
        Page page = new Page(pageNum, pageSize);
        MPJLambdaWrapper<SysUser> sysUserMPJLambdaWrapper=lambdaWrapper( param);
        IPage<UserPageVO>iPage=  this.selectJoinListPage(page,UserPageVO.class,sysUserMPJLambdaWrapper);

        for (UserPageVO record : iPage.getRecords()) {
            Set<String> strings=redisUtil.getKeyBatch(RedisEnum.LOGIN_INFO,record.getId());
            if(strings.size()>0){
                record.setOnLine(YesOrNoEnum.YES);
            }
        }
        return R.ok(iPage);
    }

    @Override
    public R<UserInfoVO> userQuery(String userId) {
        UserInfoVO userInfoVO=BeanUtil.copyProperties(this.getById(userId), UserInfoVO.class);

        if (userInfoVO!=null) {
            Function<Object, String> f = (o -> o.toString());
            userInfoVO.setRoleIds(sysUserOrRoleService.listObjs(new LambdaQueryWrapper<SysUserOrRole>().eq(SysUserOrRole::getUserId,userId).select(SysUserOrRole::getRoleId),f));
        }
        return R.ok(userInfoVO);
    }

    @Override
    public R userSave(UserSaveParam userSaveParam) {
        try
        {
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            userSaveParam.setPassword(passwordEncoder.encode(userSaveParam.getPassword()));
            SysUser sysUser=BeanUtil.copyProperties(userSaveParam,SysUser.class);
            this.save(sysUser);
            if(CollUtil.isNotEmpty(userSaveParam.getRoleIds())){
                List<SysUserOrRole> sysUserOrRoleList=new ArrayList<>();
                for (String roleId : userSaveParam.getRoleIds()) {
                    sysUserOrRoleList.add(new SysUserOrRole(sysUser.getId(),Long.valueOf(roleId)));
                }
                if(CollUtil.isNotEmpty(sysUserOrRoleList)){
                    sysUserOrRoleService.saveBatch(sysUserOrRoleList);
                }
            }


        } catch (Exception e) {
            if(e instanceof DuplicateKeyException){

                return R.error("当前用户名已存在");
            }
            throw new RuntimeException(e);
        }
        return R.ok();

    }

    @Override
    public R userUpdate(UserUpdateParam userUpdateParam, String id) {


        LambdaUpdateWrapper<SysUser> sysUserLambdaUpdateWrapper=new LambdaUpdateWrapper<>();
        sysUserLambdaUpdateWrapper.set(SysUser::getNickName,userUpdateParam.getNickName());
        sysUserLambdaUpdateWrapper.set(SysUser::getPhone,userUpdateParam.getPhone());
        sysUserLambdaUpdateWrapper.set(SysUser::getEmail,userUpdateParam.getEmail());
        sysUserLambdaUpdateWrapper.set(SysUser::getIsEnabled,userUpdateParam.getIsEnabled());
        sysUserLambdaUpdateWrapper.set(SysUser::getExpiredDate,userUpdateParam.getExpiredDate());
        sysUserLambdaUpdateWrapper.eq(SysUser::getId,id);
        this.update(sysUserLambdaUpdateWrapper);

        if(CollUtil.isNotEmpty(userUpdateParam.getRoleIds())){
            Long user=Long.valueOf(id);
            LambdaQueryWrapper<SysUserOrRole> sysUserOrRoleLambdaQueryWrapper=new LambdaQueryWrapper<>();
            sysUserOrRoleLambdaQueryWrapper.eq(SysUserOrRole::getUserId,id);
            sysUserOrRoleService.remove(sysUserOrRoleLambdaQueryWrapper);
            List<SysUserOrRole> sysUserOrRoleList=new ArrayList<>();
            for (String roleId : userUpdateParam.getRoleIds()) {
                sysUserOrRoleList.add(new SysUserOrRole(user,Long.valueOf(roleId)));
            }
            if(CollUtil.isNotEmpty(sysUserOrRoleList)){
                sysUserOrRoleService.saveBatch(sysUserOrRoleList);
            }
        }
        return R.ok();
    }

    @Override
    public R userPassword(UserPasswordParam userPasswordParam, String id) {
        try {
            BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
            LambdaUpdateWrapper<SysUser> sysUserLambdaUpdateWrapper=new LambdaUpdateWrapper<>();
            sysUserLambdaUpdateWrapper.eq(SysUser::getId,id);
            sysUserLambdaUpdateWrapper.set(SysUser::getPassword,passwordEncoder.encode(userPasswordParam.getPassword()));
            this.update(sysUserLambdaUpdateWrapper);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return R.ok();
    }

    @Override
    public R userDelete(String userId) {
        this.removeById(userId);
        return R.ok();
    }

    @Override
    public R resettingPwd(String userId) {

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        LambdaUpdateWrapper<SysUser> sysUserLambdaUpdateWrapper=new LambdaUpdateWrapper<>();
        sysUserLambdaUpdateWrapper.eq(SysUser::getId,userId);
        sysUserLambdaUpdateWrapper.set(SysUser::getPassword,passwordEncoder.encode(sysConfigsService.getSysConfigs(ConfigsEnum.LOGIN_DEFAULT_PASSWORD)));

        this.update(sysUserLambdaUpdateWrapper);
        return R.ok("重置密码成功，默认密码为:["+ConfigsEnum.LOGIN_DEFAULT_PASSWORD.getConfigValue()+"],请尽快修改更安全的密码");
    }


    /**
     * 组装查询调节扣
     * @param param
     * @return
     */
    private   MPJLambdaWrapper<SysUser> lambdaWrapper(UserPageParam param){
        MPJLambdaWrapper<SysUser> sysUserMPJLambdaWrapper=new MPJLambdaWrapper<>();


        sysUserMPJLambdaWrapper.selectAs(SysUser::getId,UserPageVO::getId);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getUserName,UserPageVO::getUserName);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getNickName,UserPageVO::getNickName);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getDepartmentId,UserPageVO::getDepartmentId);
        sysUserMPJLambdaWrapper.selectAs(SysDepartment::getDepartmentName,UserPageVO::getDepartmentName);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getPhone,UserPageVO::getPhone);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getEmail,UserPageVO::getEmail);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getIsEnabled,UserPageVO::getIsEnabled);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getExpiredDate,UserPageVO::getExpiredDate);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getLoginDate,UserPageVO::getLoginDate);
        sysUserMPJLambdaWrapper.selectAs(SysUser::getCreatedTime,UserPageVO::getCreatedTime);

        sysUserMPJLambdaWrapper.leftJoin(SysDepartment.class,SysDepartment::getId,SysUser::getDepartmentId);

        sysUserMPJLambdaWrapper.like(StrUtil.isNotBlank(param.getUserName()), SysUser::getUserName, param.getUserName());
        sysUserMPJLambdaWrapper.like(StrUtil.isNotBlank(param.getEmail()), SysUser::getEmail, param.getEmail());
        sysUserMPJLambdaWrapper.like(StrUtil.isNotBlank(param.getNickName()), SysUser::getNickName, param.getNickName());
        sysUserMPJLambdaWrapper.like(StrUtil.isNotBlank(param.getPhone()), SysUser::getPhone, param.getPhone());

        sysUserMPJLambdaWrapper.eq(param.getIsEnabled()!=null, SysUser::getIsEnabled, param.getIsEnabled());
        sysUserMPJLambdaWrapper.ge(param.getCreatedTimeStart()!=null, SysUser::getCreatedTime, param.getCreatedTimeStart());
        sysUserMPJLambdaWrapper.le(param.getCreatedTimeEnd()!=null, SysUser::getCreatedTime, param.getCreatedTimeEnd());
        sysUserMPJLambdaWrapper.ge(param.getLoginDateStart()!=null, SysUser::getCreatedTime, param.getLoginDateStart());
        sysUserMPJLambdaWrapper.le(param.getLoginDateEnd()!=null, SysUser::getCreatedTime, param.getLoginDateEnd());

        if(StrUtil.isNotBlank(param.getDepartmentId())){
            sysUserMPJLambdaWrapper.in( SysUser::getDepartmentId, sysDepartmentService.departmentIdList(param.getDepartmentId()));
        }else{
            sysUserMPJLambdaWrapper.in( SysUser::getDepartmentId, sysDepartmentService.departmentIdList(SecurityUtil.getLoginUser().getDepartment().getDepartmentId()));
        }



        return sysUserMPJLambdaWrapper;
    }




}

